// Copyright (c) 2014 Dan Nagle. All rights reserved.
//
// Licensed MIT: https://github.com/dannagle/PacketSender-Android
package com.packetsender.android;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.NetworkOnMainThreadException;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.os.IBinder;
import android.util.Log;
import android.widget.ImageButton;
import android.widget.RemoteViews;
import android.app.Service;
import android.widget.Toast;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import static com.packetsender.android.MainActivity.isMyServiceRunning;
public class PacketSenderWidget extends AppWidgetProvider {
public static final String WIDGET_CLICKED = "com.packetsender.android.widgetclicked";
public static final String WIDGET_ID = "com.packetsender.android.widgetid";
public DataStorage dataStore;
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onDeleted(context, appWidgetIds);
//Toast.makeText(context, "onDeleted()", Toast.LENGTH_LONG).show();
updateWidgets(context);
}
@Override
public void onDisabled(Context context) {
// TODO Auto-generated method stub
super.onDisabled(context);
//Toast.makeText(context, "onDisabled()", Toast.LENGTH_LONG).show();
updateWidgets(context);
}
@Override
public void onEnabled(Context context) {
// TODO Auto-generated method stub
super.onEnabled(context);
//Toast.makeText(context, "onEnabled()", Toast.LENGTH_LONG).show();
updateWidgets(context);
}
private static AppWidgetManager getAppWidgetManager(Context context) {
return AppWidgetManager.getInstance(context);
}
private static int[] getAppWidgetIds(Context context) {
int[] appWidgetIds = getAppWidgetManager(context).getAppWidgetIds(new ComponentName(context, PacketSenderWidget.class));
return appWidgetIds;
}
public static void updateWidgets(Context context) {
RemoteViews remoteViews;
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
AppWidgetManager appWidgetManager = getAppWidgetManager(context);
int[] appWidgetIds = getAppWidgetIds(context);
for(int ID : appWidgetIds ){
Log.d("widget", DataStorage.FILE_LINE("Do the on update for " + ID));
remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
DataStorage dataStore = new DataStorage(
context.getSharedPreferences(DataStorage.PREFS_SETTINGS_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_SAVEDPACKETS_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_SERVICELOG_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_MAINTRAFFICLOG_NAME, 0)
);
Packet widgetPacket = dataStore.getWidgetPacket(ID);
//PendingIntent selfIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setTextViewText(R.id.widget_textview, widgetPacket.name);
if(widgetPacket.tcpOrUdp.equalsIgnoreCase("tcp")) {
remoteViews.setImageViewResource(R.id.widget_imagebutton, R.drawable.tx_tcp);
} else {
remoteViews.setImageViewResource(R.id.widget_imagebutton, R.drawable.tx_udp);
}
Intent intent = new Intent(context, PacketSenderWidget.class);
intent.setAction(PacketSenderWidget.WIDGET_CLICKED);
intent.putExtra(PacketSenderWidget.WIDGET_ID, ID);
PendingIntent selfIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_ONE_SHOT);
remoteViews.setTextViewText(R.id.widget_textview, widgetPacket.name);
remoteViews.setOnClickPendingIntent(R.id.widget_imagebutton, selfIntent);
appWidgetManager.updateAppWidget(ID, remoteViews);
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
updateWidgets(context);
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
Log.d("widget", DataStorage.FILE_LINE("Do the onreceive"));
if (WIDGET_CLICKED.equals(intent.getAction())) {
int extra = intent.getIntExtra(WIDGET_ID, 0);
Log.d("widget", DataStorage.FILE_LINE("extra is " + extra));
dataStore = new DataStorage(
context.getSharedPreferences(DataStorage.PREFS_SETTINGS_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_SAVEDPACKETS_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_SERVICELOG_NAME, 0),
context.getSharedPreferences(DataStorage.PREFS_MAINTRAFFICLOG_NAME, 0)
);
Packet sendPacket = dataStore.getWidgetPacket(extra);
sendPacket.nowMe();
Log.i("widget", DataStorage.FILE_LINE("widget says to send " + sendPacket.name));
//launching service is apparently very unreliable. Do the update here.
new SendPacketsTask().execute(sendPacket);
updateWidgets(context);
/*
dataStore.sendPacketToService(sendPacket);
if(!isMyServiceRunning(context))
{
Intent serviceIntent = new Intent(context, PacketListenerService.class);
context.startService(serviceIntent);
}
*/
}
}
private class SendPacketsTask extends AsyncTask<Packet, Void, Void> {
// Do the long-running work in here
protected Void doInBackground(Packet... params) {
Log.d("SendPacketsTask", DataStorage.FILE_LINE("length" + params.length));
Packet fetchedPacket = params[0];
Log.d("SendPacketsTask", DataStorage.FILE_LINE("send packet " + fetchedPacket.toString()));
//if(1+1 == 2) return null;
if(fetchedPacket.tcpOrUdp.equalsIgnoreCase("tcp")) {
} else {
//dataStore.SavePacket(storepacket);
try {
ByteBuffer buf = ByteBuffer.allocate(fetchedPacket.data.length);
buf.clear();
buf.put(fetchedPacket.data);
buf.flip();
DatagramSocket udpSocket;
DatagramPacket udpPacket;
byte[] buffer = new byte[2048];
// Create a packet to receive data into the buffer
udpPacket = new DatagramPacket(buf.array(), buf.array().length);
udpSocket = new DatagramSocket(null);
udpSocket.setReuseAddress(true);
InetSocketAddress clientAddress = new InetSocketAddress(fetchedPacket.toIP, fetchedPacket.port);
udpSocket.connect(clientAddress);
udpSocket.send(udpPacket);
udpSocket.close();
fetchedPacket.fromIP = "You";
fetchedPacket.nowMe();
dataStore.saveTrafficPacket(fetchedPacket);
Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
try {
Socket clientSocket;
InetSocketAddress translateSocket = new InetSocketAddress(fetchedPacket.toIP, fetchedPacket.port);
clientSocket = new Socket(translateSocket.getHostName(), translateSocket.getPort());
clientSocket.setReuseAddress(true);
clientSocket.setSoTimeout(2000); // 2 second timeout
DataOutputStream out = new DataOutputStream(
clientSocket.getOutputStream());
DataInputStream in = new DataInputStream(
clientSocket.getInputStream());
out.write(fetchedPacket.data);
Packet savePacket = fetchedPacket.duplicate();
savePacket.fromIP = "You";
savePacket.nowMe();
dataStore.saveTrafficPacket(savePacket);
Log.d("widget", DataStorage.FILE_LINE("sendBroadcast"));
byte[] buffer = new byte[1024];
int received = in.read(buffer);
if(received > 0) {
byte[] bufferConvert = new byte[received];
System.arraycopy(buffer, 0, bufferConvert, 0, received);
Log.i("widget",DataStorage.FILE_LINE("FROM SERVER: " + Packet.toHex(bufferConvert)));
savePacket = fetchedPacket.duplicate();
savePacket.nowMe();
savePacket.data = bufferConvert;
savePacket.fromIP = fetchedPacket.toIP;
savePacket.fromPort = fetchedPacket.port;
savePacket.toIP = "You";
savePacket.port = fetchedPacket.fromPort;
fetchedPacket.nowMe();
dataStore.saveTrafficPacket(savePacket);
Log.d("widget", DataStorage.FILE_LINE("sendBroadcast"));
}
out.close();
in.close();
clientSocket.close();
} catch (SocketTimeoutException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.w("service",DataStorage.FILE_LINE("SocketTimeoutException: " + sw.toString()));
} catch (NetworkOnMainThreadException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.w("service",DataStorage.FILE_LINE("NetworkOnMainThreadException: " + sw.toString()));
} catch (UnknownHostException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.w("service", DataStorage.FILE_LINE("UnknownHostException: " + sw.toString()));
Log.d("service",DataStorage.FILE_LINE("Saving the error to packet."));
fetchedPacket.errorString = "Unknown host";
fetchedPacket.nowMe();
dataStore.saveTrafficPacket(fetchedPacket);
} catch (IOException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.w("service", DataStorage.FILE_LINE("IOException: " + sw.toString())); //failed to connect error.
Log.d("service", DataStorage.FILE_LINE("Saving the error to packet."));
fetchedPacket.errorString = "Connection error";
fetchedPacket.nowMe();
dataStore.saveTrafficPacket(fetchedPacket);
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
Log.w("service",DataStorage.FILE_LINE("Exception: " + sw.toString()));
}
return null;
}
protected void onProgressUpdate()
{
//setProgressPercent(progress[0]);
}
protected void onPostExecute(boolean result)
{
//showDialog("Downloaded " + result + " bytes");
}
}
}